﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ArgusLib
{
	public static class Log
	{
		static Stream stream;
		static TextWriter textWriter;
		static object levelLock;
		static bool writeLevels;

		static int level;

		public static int Level
		{
			get { lock (Log.levelLock) { return Log.level; } }
			set
			{
				lock (Log.levelLock)
				{
					if (value < 0)
						Log.level = 0;
					else
						Log.level = value;
				}
			}
		}

		public static Stream Stream
		{
			get { return Log.stream; }
			set
			{
				if (value == null)
				{
					Log.stream = null;
					Log.textWriter = Console.Out;
				}
				else
				{
					Log.stream = value;
					Log.textWriter = new StreamWriter(value);
				}
			}
		}

		public static bool AutoFlush { get; set; }

		static Log()
		{
			Log.textWriter = Console.Out;
			Log.levelLock = new object();
			Log.level = 0;
			Log.AutoFlush = true;
			Log.writeLevels = true;
		}

		public static void IncrementLevel() { Log.Level += 1; }
		public static void DecrementLevel() { Log.Level -= 1; }

		static void WriteLevel()
		{
			if (Log.writeLevels == false)
				return;
			if (Log.textWriter == null)
				return;

			string s = new string('\t', Log.Level);
			Log.textWriter.Write(s);
		}

		public static void Write(bool value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(char value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(char[] value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(decimal value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(double value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(int value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(long value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(object value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(float value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(string value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(uint value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(ulong value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(string format, params object[] value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(format, value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void Write(char[] buffer, int index, int count)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.Write(buffer, index, count);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = false;
		}

		public static void WriteLine(bool value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(char value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(char[] value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(decimal value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(double value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(int value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(long value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(object value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(float value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(string value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(uint value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(ulong value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(string format, params object[] value)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(format, value);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine(char[] buffer, int index, int count)
		{
			if (Log.textWriter == null)
				return;

			Log.WriteLevel();
			Log.textWriter.WriteLine(buffer, index, count);
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}

		public static void WriteLine()
		{
			if (Log.textWriter == null)
				return;

			Log.textWriter.WriteLine();
			if (Log.AutoFlush == true)
				Log.textWriter.Flush();

			Log.writeLevels = true;
		}
	}
}
